#include "playvideo.h"
#include <QDebug>

PlayVideo::PlayVideo(QThread *parent) : QThread(parent)
{
}

PlayVideo::~PlayVideo()
{
    if(this->capture)
    {
        this->capture->release();
        delete  this->capture;
    }
}

void PlayVideo::run()
{
    this->capture = new VideoCapture(0);
    if(capture->isOpened())
    {
        bool foundTarget = false;                //记录是否为要追踪的目标
        bool targetCaptured = false;             // 追踪目标是否已经捕获的标志
        Rect previousBoundingBox;                // 记录上一个边界框的位置
        int stableFrameCount = 0;                // 记录目标保持稳定的帧数
        const int requiredStableFrames = 30;     // 目标保持稳定的帧数阈值
        const double positionThreshold = 10.0;   // 位置变化的阈值
        Mat mat;
        Mat gauss;
        Mat median;
        Mat morphology;
        Mat gray;
        Mat edges;
        while(!(this->isInterruptionRequested()))
        {
            *capture >> mat;
            if(!(mat.empty()))
            {
                //重置检测标志位
                foundTarget = false;

                //转换成灰度图
                cvtColor(mat, gray, COLOR_BGR2GRAY);

                //进行高斯模糊减少高频噪声
                GaussianBlur(gray, gauss, Size(9, 9), 0);

                //中值滤波进一步去除噪声
                medianBlur(gauss, median, 9);

                //形态学(闭运算)去除小噪点
                morphologyEx(median, morphology, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(9, 9)));

                //进行边缘检测
                Canny(morphology, edges, 50, 150);

                //进行轮廓检测
                vector<vector<Point>> contours;
                vector<Vec4i> hierarchy;  // 保存层次信息
                findContours(edges, contours, hierarchy, RETR_CCOMP,CHAIN_APPROX_SIMPLE);

                //遍历轮廓，绘制矩形框进行标记,同时过滤小框
                Rect boundingbox;   // 记录当前帧中的边界框
                for(size_t i = 0; i < contours.size(); i++)
                {
                    if(hierarchy[i][3] == -1) //如果当前轮廓没有父轮廓
                    {
                        boundingbox = boundingRect(contours[i]);
                        foundTarget = true; //代表找到了目标
                        rectangle(mat, boundingbox, Scalar(0, 255, 0), 2);
                    }

                }

                if(foundTarget)
                {
                    //计算当前目标与上一帧位置的差异
                    double deltaX = abs(boundingbox.x - previousBoundingBox.x);
                    double deltaY = abs(boundingbox.y - previousBoundingBox.y);

                    //如果位置变化小于阈值，增加当前的稳定帧数
                    if(deltaX < positionThreshold && deltaY < positionThreshold)
                    {
                        stableFrameCount++;
                    }
                    else
                    {
                        stableFrameCount = 0;
                    }

                    //更新前一个边界框的位置
                    previousBoundingBox = boundingbox;

                    //当满足足够的帧数后，发送信号给主线程
                    if(stableFrameCount >= requiredStableFrames && !targetCaptured)
                    {
                        QPoint centerPoint(boundingbox.x + boundingbox.width / 2, boundingbox.y + boundingbox.height / 2);
                        qDebug() << "x = " << centerPoint.x() << ", y = " << centerPoint.y();
                        emit this->SendPoint(centerPoint); // 发送中心点坐标
                        emit this->SendRect(boundingbox);   //发送边界框
                        //将是否捕获过设置为true;
                        targetCaptured = true;
                    }
                }
                else
                {
                    // 没有检测到目标时，重置标志和稳定帧数
                    targetCaptured = false;
                    stableFrameCount = 0;
                }
                //发送处理后的图片给主线程
                emit this->SendVideo(this->MatToImage(mat));
            }
            QThread::msleep(30);    //延迟采集
        }
    }
}

QImage PlayVideo::MatToImage(Mat &mat)
{
    QImage image;
    switch (mat.type())
    {
        case CV_8UC1:
        {
            const uchar* pSrc = (const uchar*)mat.data;
            image = QImage(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8);
            return image;
        }
        case CV_8UC3:
        {
            const uchar* pSrc = (const uchar*)mat.data;
            image = QImage(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
            return image.rgbSwapped();
        }
        case CV_8UC4:
        {
            const uchar* pSrc = (const uchar*)mat.data;
            image = QImage(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
            return image.copy();
        }
        default:
        {
            mat.convertTo(mat, CV_8UC3);
            const uchar* pSrc = (const uchar*)mat.data;
            image = QImage(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
            return image.rgbSwapped();
        }
    }
}
